/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package OtrosTPs.TP1;

import java.util.ArrayList;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

/**
 *
 * @author ivanpianetti
 */
public class Ejerc4 {

    private static Double factorNormal = 100.0;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Double[] v1 = new Double[4];
        Double[] v2 = new Double[4];
        Double[] v3 = new Double[4];
        Double[] v4 = new Double[4];
        Double[] v5 = new Double[4];
        Double[] v6 = new Double[4];

        v1[0] = 32.0;
        v1[1] = 1.7;
        v1[2] = 8.0;
        v1[3] = 70.0;
        System.out.println("V1=" + toStringVect(v1));
        v1 = normalizar(v1);
        System.out.println("V1n=" + toStringVect(v1) + "\n");

        v2[0] = 21.0;
        v2[1] = 1.6;
        v2[2] = 3.0;
        v2[3] = 53.0;
        System.out.println("V2=" + toStringVect(v2));
        v2 = normalizar(v2);
        System.out.println("V2n=" + toStringVect(v2) + "\n");

        v3[0] = 17.0;
        v3[1] = 1.85;
        v3[2] = 6.0;
        v3[3] = 68.0;
        System.out.println("V3=" + toStringVect(v3));
        v3 = normalizar(v3);
        System.out.println("V3n=" + toStringVect(v3) + "\n");

        v4[0] = 38.0;
        v4[1] = 1.68;
        v4[2] = 5.0;
        v4[3] = 89.0;
        System.out.println("V4=" + toStringVect(v4));
        v4 = normalizar(v4);
        System.out.println("V4n=" + toStringVect(v4) + "\n");

        v5[0] = 52.0;
        v5[1] = 1.73;
        v5[2] = 9.0;
        v5[3] = 65.0;
        System.out.println("V5=" + toStringVect(v5));
        v5 = normalizar(v5);
        System.out.println("V5n=" + toStringVect(v5) + "\n");

        v6[0] = 20.0;
        v6[1] = 1.5;
        v6[2] = 6.0;
        v6[3] = 55.0;
        System.out.println("V6=" + toStringVect(v6));
        v6 = normalizar(v6);
        System.out.println("V6n=" + toStringVect(v6) + "\n");

        System.out.println("--------Parte a-----------");
        System.out.println("Distancia Manhattan (v1n;v2n)= " + dManhattan(v1, v2));
        System.out.println("Distancia Manhattan (v1n;v3n)= " + dManhattan(v1, v3));
        System.out.println("Distancia Manhattan (v1n;v4n)= " + dManhattan(v1, v4));
        System.out.println("Distancia Manhattan (v1n;v5n)= " + dManhattan(v1, v5));
        System.out.println("Distancia Manhattan (v2n;v3n)= " + dManhattan(v2, v3));
        System.out.println("Distancia Manhattan (v2n;v4n)= " + dManhattan(v2, v4));
        System.out.println("Distancia Manhattan (v2n;v5n)= " + dManhattan(v2, v5));
        System.out.println("Distancia Manhattan (v3n;v4n)= " + dManhattan(v3, v4));
        System.out.println("Distancia Manhattan (v3n;v5n)= " + dManhattan(v3, v5));
        System.out.println("Distancia Manhattan (v4n;v5n)= " + dManhattan(v4, v5));
        System.out.println("#################");
        System.out.println("Distancia Euclidiana (v1n;v2n)= " + dEuclidiana(v1, v2));
        System.out.println("Distancia Euclidiana (v1n;v2n)= " + dEuclidiana(v1, v3));
        System.out.println("Distancia Euclidiana (v1n;v2n)= " + dEuclidiana(v1, v4));
        System.out.println("Distancia Euclidiana (v1n;v2n)= " + dEuclidiana(v1, v5));
        System.out.println("Distancia Euclidiana (v1n;v2n)= " + dEuclidiana(v2, v3));
        System.out.println("Distancia Euclidiana (v1n;v2n)= " + dEuclidiana(v2, v4));
        System.out.println("Distancia Euclidiana (v1n;v2n)= " + dEuclidiana(v2, v5));
        System.out.println("Distancia Euclidiana (v1n;v2n)= " + dEuclidiana(v3, v4));
        System.out.println("Distancia Euclidiana (v1n;v2n)= " + dEuclidiana(v3, v5));
        System.out.println("Distancia Euclidiana (v1n;v2n)= " + dEuclidiana(v4, v5));
        System.out.println("#################");
        System.out.println("Distancia Máxima (v1n;v2n)= " + dMaxima(v1, v2));
        System.out.println("Distancia Máxima (v1n;v2n)= " + dMaxima(v1, v3));
        System.out.println("Distancia Máxima (v1n;v2n)= " + dMaxima(v1, v4));
        System.out.println("Distancia Máxima (v1n;v2n)= " + dMaxima(v1, v5));
        System.out.println("Distancia Máxima (v1n;v2n)= " + dMaxima(v2, v3));
        System.out.println("Distancia Máxima (v1n;v2n)= " + dMaxima(v2, v4));
        System.out.println("Distancia Máxima (v1n;v2n)= " + dMaxima(v2, v5));
        System.out.println("Distancia Máxima (v1n;v2n)= " + dMaxima(v3, v4));
        System.out.println("Distancia Máxima (v1n;v2n)= " + dMaxima(v3, v5));
        System.out.println("Distancia Máxima (v1n;v2n)= " + dMaxima(v4, v5));

        System.out.println("\n--------Parte b-----------");
        System.out.println("Las cadenas mas cercanas a v6n son: ");
        ArrayList<Double[]> lista = new ArrayList<Double[]>();
        lista.add(v1);
        lista.add(v2);
        lista.add(v3);
        lista.add(v4);
        lista.add(v5);

//        System.out.println("Manhattan= " + getNNManhattan(lista, v6));
//        System.out.println("Euclidiana= " + getNNEuclidiana(lista, v6));
//        System.out.println("Máxima= " + getNNMaxima(lista, v6));

        System.out.println("Distancia Manhattan (v1n;v6n)= " + dManhattan(v1, v6));
        System.out.println("Distancia Manhattan (v2n;v6n)= " + dManhattan(v2, v6));
        System.out.println("Distancia Manhattan (v3n;v6n)= " + dManhattan(v3, v6));
        System.out.println("Distancia Manhattan (v4n;v6n)= " + dManhattan(v4, v6));
        System.out.println("Distancia Manhattan (v5n;v6n)= " + dManhattan(v5, v6));
        System.out.println("#################");
        System.out.println("Distancia Euclidiana (v1n;v6n)= " + dEuclidiana(v1, v6));
        System.out.println("Distancia Euclidiana (v2n;v6n)= " + dEuclidiana(v2, v6));
        System.out.println("Distancia Euclidiana (v3n;v6n)= " + dEuclidiana(v3, v6));
        System.out.println("Distancia Euclidiana (v4n;v6n)= " + dEuclidiana(v4, v6));
        System.out.println("Distancia Euclidiana (v5n;v6n)= " + dEuclidiana(v5, v6));
        System.out.println("#################");
        System.out.println("Distancia Máxima (v1n;v6n)= " + dMaxima(v1, v6));
        System.out.println("Distancia Máxima (v2n;v6n)= " + dMaxima(v2, v6));
        System.out.println("Distancia Máxima (v3n;v6n)= " + dMaxima(v3, v6));
        System.out.println("Distancia Máxima (v4n;v6n)= " + dMaxima(v4, v6));
        System.out.println("Distancia Máxima (v5n;v6n)= " + dMaxima(v5, v6));
    }

    private static Double[] normalizar(Double[] vect) {
        //Edad
        vect[0] = EdadRango.calcNormal(vect[0]);

        //Estatura
        vect[1] = EstaturaRango.calcNormal(vect[1]);

        //Colo Pelo
        vect[2] = ColoPeloRango.calcNormal(vect[2]);

        //Peso
        vect[3] = PesoRango.calcNormal(vect[3]);
        return vect;
    }

    private static String toStringVect(Double[] v1) {
        return "(" + v1[0] + ";" + v1[1] + ";" + v1[2] + ";" + v1[3] + ")";
    }

    private static Double dManhattan(Double[] v1, Double[] v2) {
        Double d = 0.0;
        for (int i = 0; i < v1.length; i++) {
            Double difABS = Math.abs(v1[i] - v2[i]);
            d = d + difABS;
        }
        return d;
    }

    private static Double dEuclidiana(Double[] v1, Double[] v2) {
        Double d = 0.0;
        for (int i = 0; i < v1.length; i++) {
            Double difCuadrado = Math.pow(v1[i] - v2[i], 2);
            d = d + difCuadrado;
        }
        return Math.sqrt(d);
    }

    private static Double dMaxima(Double[] v1, Double[] v2) {
        SortedSet<Double> listaABS = new TreeSet<Double>();
        for (int i = 0; i < v1.length; i++) {
            listaABS.add(Math.abs(v1[i] - v2[i]));
        }
        Double maximo = listaABS.last();
        return maximo;
    }

    private static Double getNNManhattan(ArrayList<Double[]> lista, Double[] v6) {
        Double result = 0.0;
//        Set<Object> distanciasLista = new TreeSet<Object>();
        for (Double[] elem : lista) {
            Double dist = dManhattan(elem, v6);
            if (dist > result) {
                result = dist;
            }
//            distanciasLista.add(dManhattan(elem, v6));
        }
        return result;
    }

    private static String getNNEuclidiana(ArrayList<Double[]> lista, Double[] v6) {
        throw new UnsupportedOperationException("Not yet implemented");
    }

    private static String getNNMaxima(ArrayList<Double[]> lista, Double[] v6) {
        throw new UnsupportedOperationException("Not yet implemented");
    }

    /**
     * @TODO Implementar una interfaz Rango o algo mas para factorizar las
     * siguientes clases!
     */
    private static class EdadRango {

        public static Double INF = 10.0;
        public static Double SUP = 90.0;

        public static Double calcNormal(Double edad) {
            return (edad - EdadRango.INF) * factorNormal / (EdadRango.SUP - EdadRango.INF);
        }
    }

    private static class EstaturaRango {

        public static Double INF = 1.0;
        public static Double SUP = 2.2;

        public static Double calcNormal(Double estatura) {
            return (estatura - EstaturaRango.INF) * factorNormal / (EstaturaRango.SUP - EstaturaRango.INF);
        }
    }

    private static class ColoPeloRango {

        public static Double INF = 1.0;
        public static Double SUP = 10.0;

        public static Double calcNormal(Double coloPelo) {
            return (coloPelo - ColoPeloRango.INF) * factorNormal / (ColoPeloRango.SUP - ColoPeloRango.INF);
        }
    }

    private static class PesoRango {

        public static Double INF = 20.0;
        public static Double SUP = 150.0;

        public static Double calcNormal(Double peso) {
            return (peso - PesoRango.INF) * factorNormal / (PesoRango.SUP - PesoRango.INF);
        }
    }
}
